#include "bhvr.h"

SBehavior::SBehavior(QPoint initPos, QSize initSize, QRect bounds)
{
    x = xz = initPos.x();
    y = yz = initPos.y();
    w = wz = initSize.width();
    h = hz = initSize.height();

    vx = vy = 0;
    vw = vh = 0;

    Xmin = bounds.left();
    Ymin = bounds.top();
    Xmax = bounds.right();
    Ymax = bounds.bottom();

    m = 1;//5;
    //r = 64;
    g = 0;//9.81;
    k = 0.9;
    Rv = 0.4;//0.6;//55;
    Gr = 3;

    oldBounce = false;

    velocityCapture = false;
    inList = false;
    reachSignalEmitted = true;
}
//---------------------------------------------------------------------------

void SBehavior::Integrate(float dt)
{
    FZone = bzIn;
    SBounceEdges edges;
    edges.left = edges.top = edges.right = edges.bottom = false;
    bool bounce = false;

    if (y+h>Ymax && vy>=0)
        edges.bottom = bounce = true;

    if (y-h<Ymin && vy<=0)
        edges.top = bounce = true;

    if (x+w>Xmax && vx>=0)
        edges.right = bounce = true;

    if (x-w<Xmin && vx<=0)
        edges.left = bounce = true;

    if (bounce)
        FZone = bzOut;

    bool doBounce = bounce && !oldBounce;
    oldBounce = bounce;

    if (abs(x-Xmax/2) > Xmax/2+w || abs(y-Ymax/2) > Ymax/2+h)
        FZone = bzAway;

    bounceEvent(doBounce, edges);

    if (doBounce)
        emit onBounce(edges);

    if (SizeReached())
    {
        if (!reachSignalEmitted)
            emit targetSizeAchieved();
        reachSignalEmitted = true;
    }
    else
    {
        reachSignalEmitted = false;
    }
}
//---------------------------------------------------------------------------

void SBehavior::bounceEvent(bool collide, SBounceEdges &edges)
{
    if (edges.left)
    {
        x = xz = Xmin + w;
        vx = 0;
    }
    if (edges.top)
    {
        y = yz = Ymin + h;
        vy = 0;
    }
    if (edges.right)
    {
        x = xz = Xmax - w;
        vx = 0;
    }
    if (edges.bottom)
    {
        y = yz = Ymax - h;
        vy = 0;
    }
}
//---------------------------------------------------------------------------

bool SBehavior::SizeReached()
{
    return (fabs(w-wz)<0.5 && fabs(h-hz)<0.5);
}

bool SBehavior::PosReached()
{
    return (fabs(x-xz)<0.5 && fabs(y-yz)<0.5);
}
//---------------------------------------------------------------------------

QPoint SBehavior::relativePos()
{
    int rx, ry;

    int xx = x - Xmin;
    int yy = y - Ymin;
    int xw = Xmax - Xmin;
    int yh = Ymax - Ymin;

    if (((xx-w <= 0) || (xx+w >= xw)) && vx)
        rx = 0;
    else
        rx = xx<xw/2? xx: xx-xw;

    if (((yy-h <= 0) || (yy+h >= yh)) && vy)
        ry = 0;
    else
        ry = yy<yh/2? yy: yy-yh;

    return QPoint(rx, ry);
}

void SBehavior::setRelativePos(int rx, int ry)
{
    int xx, yy;
    int xw = Xmax - Xmin;
    int yh = Ymax - Ymin;

    if (rx)
    {
        xx = (abs(rx)>xw/2)? xw/2: (rx<0)? xw+rx: rx;
    }
    else if (vx > 0)
    {
        xx = -w;
        //edges.left = false;
    }
    else if (vx < 0)
    {
        xx = xw + w;
        //edges.right = false;
    }

    if (ry)
    {
        yy = (abs(ry)>yh/2)? yh/2: (ry<0)? yh+ry: ry;
    }
    else if (vy > 0)
    {
        yy = -h;
        //edges.top = false;
    }
    else if (vy < 0)
    {
        yy = yh + h;
        //edges.bottom = false;
    }

    xz = x = xx + Xmin;
    yz = y = yy + Ymin;
}
//---------------------------------------------------------------------------

void SBehavior::Switch(SBehavior *&old, SBehavior* new_model)
{
    if (old)
    {
        new_model->x = old->x;
        new_model->y = old->y;
        new_model->vx = old->vx;
        new_model->vy = old->vy;
        new_model->w = old->w;
        new_model->h = old->h;
        new_model->vw = old->vw;
        new_model->vh = old->vh;
    }
    old = new_model;
}
//---------------------------------------------------------------------------

void SBehavior::stop()
{
    vx = 0;
    vy = 0;
    xz = x;
    yz = y;
}
//---------------------------------------------------------------------------
